
package com.scs.application.modules.order.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.order.consts.DictConsts;
import com.scs.application.modules.order.entity.DeliveryItem;
import com.scs.application.modules.order.entity.PurchaseOrder;
import com.scs.application.modules.order.entity.PurchaseOrderItem;
import com.scs.application.modules.order.mapper.PurchaseOrderItemMapper;
import com.scs.application.modules.order.mapper.PurchaseOrderMapper;
import com.scs.application.modules.order.request.PurchaseOrderItemQueryRequest;
import com.scs.application.modules.order.service.DeliveryItemService;
import com.scs.application.modules.order.service.DeliveryService;
import com.scs.application.modules.order.service.PurchaseOrderItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 采购订单明细 service 实现
 *
 */
@Slf4j
@Service
public class PurchaseOrderItemServiceImpl extends BaseServiceImpl<PurchaseOrderItemMapper, PurchaseOrderItem> implements PurchaseOrderItemService {

    @Autowired
    private PurchaseOrderMapper purchaseOrderMapper;

    @Autowired
    private PurchaseOrderItemMapper purchaseOrderItemMapper;

    @Autowired
    @Lazy
    private DeliveryItemService deliveryItemService;

    @Autowired
    @Lazy
    private DeliveryService deliveryService;

    @Override
    public List<PurchaseOrderItem> list(PurchaseOrderItemQueryRequest request) {
        List<PurchaseOrderItem> list = this.list(Wrappers.<PurchaseOrderItem>query()
                .eq(StringUtils.isNotBlank(request.getId()), "id", request.getId())
                .eq("po_id", request.getPoId())
                .orderByDesc("gmt_create")
        );
        return list;

    }


    @Override
    public IPage<PurchaseOrderItem> page(PurchaseOrderItemQueryRequest request) {
        IPage page = this.page(request.getPage(), Wrappers.<PurchaseOrderItem>query()
                .orderByDesc("gmt_modified")
        );
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(PurchaseOrderItem entity) {

        entity.setDeliveredQty(0.0)
                .setStoredQty(0.0)
                .setDeliveryStatus(DictConsts.STATUS_UNDELIVERY)
                .setDeliveredAmount(0.0);
        saveOrUpdate(entity);

        //更新订单总金额
        Double totalAmount = totalAmount(entity.getPoId());
        PurchaseOrder po = new PurchaseOrder();
        po.setTotalAmount(totalAmount).setId(entity.getPoId());
        purchaseOrderMapper.updateById(po);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchSave(List<PurchaseOrderItem> children) {
        if (children.isEmpty()) {
            return;
        }
        for (PurchaseOrderItem item : children) {
            item.setDeliveredQty(0.0)
                    .setStoredQty(0.0)
                    .setDeliveryStatus(DictConsts.STATUS_UNDELIVERY)
                    .setDeliveredAmount(0.0);
        }

        saveBatch(children);

        //更新订单总金额
        Double totalAmount = totalAmount(children.get(0).getPoId());
        PurchaseOrder po = new PurchaseOrder();
        po.setTotalAmount(totalAmount).setId(children.get(0).getPoId());
        purchaseOrderMapper.updateById(po);
    }

    @Override
    public Double totalAmount(String poId) {
        Double amount = baseMapper.totalAmount(poId);
        return amount == null ? 0 : amount;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(String id) {
        PurchaseOrderItem entity = getById(id);
        String poId = entity.getPoId();
        removeCascadeById(id);

        //更新订单总金额

        Double totalAmount = totalAmount(poId);
        PurchaseOrder po = new PurchaseOrder();
        po.setTotalAmount(totalAmount).setId(poId);

        purchaseOrderMapper.updateById(po);
    }

    @Override
    public void update(PurchaseOrderItem entity) {
        updateCascadeById(entity);
        //更新订单总金额
        Double totalAmount = totalAmount(entity.getPoId());
        PurchaseOrder po = new PurchaseOrder();
        po.setTotalAmount(totalAmount).setId(entity.getPoId());
        purchaseOrderMapper.updateById(po);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDeliveredQty(String poId) {
        List<PurchaseOrderItem> poItems = this.list(Wrappers.<PurchaseOrderItem>query().eq("po_id",poId));
        if (ObjectUtil.length(poItems) == 0) {
            return;
        }
        List<String> poItemIdList = poItems.stream().map(item -> item.getId()).collect(Collectors.toList());
        List<DeliveryItem> deliveryItemList = deliveryItemService.list(Wrappers.<DeliveryItem>query().in("po_item_id",poItemIdList));
        if (ObjectUtil.length(deliveryItemList) == 0) {
            poItems.stream().forEach(item -> {
                item.setDeliveredQty(0d).setDeliveredAmount(0d);
            });
            this.updateBatchById(poItems);
            return;
        }
        Map<String,List<DeliveryItem>> mapByPoItemId = deliveryItemList.stream().collect(Collectors.groupingBy(DeliveryItem::getPoItemId));
        Double deliveredQty = 0d;
        Double deliveredAmount = 0d;
        for(PurchaseOrderItem orderItem : poItems) {
            deliveredQty = 0d;
            deliveredAmount = 0d;
            if (mapByPoItemId.containsKey(orderItem.getId())) {
                deliveredQty = mapByPoItemId.get(orderItem.getId()).stream().mapToDouble(DeliveryItem::getQty).sum();
                deliveredAmount = mapByPoItemId.get(orderItem.getId()).stream().mapToDouble(item -> item.getPrice() * item.getQty()).sum();
            }
            orderItem.setDeliveredQty(deliveredQty).setDeliveredAmount(deliveredAmount);
        }
        this.updateBatchById(poItems);
    }

    private void updatePoAmount(String poId) {
        //更新订单总金额
        Double totalAmount = totalAmount(poId);
        PurchaseOrder po = new PurchaseOrder();
        po.setTotalAmount(totalAmount).setId(poId);
        purchaseOrderMapper.updateById(po);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeCascadeBatchByIds(Collection<? extends Serializable> idList) {
        List<String> poIdList = this.listByIds(idList).stream().map(PurchaseOrderItem::getPoId).distinct().collect(Collectors.toList());
        super.removeCascadeBatchByIds(idList);

        poIdList.stream().forEach(poId -> {
            updatePoAmount(poId);
        });

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(PurchaseOrderItem entity) {
        super.saveOrUpdate(entity);
        updatePoAmount(entity.getPoId());
        return true;
    }
}
